package flex.cc.nursing.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import flex.cc.basicinformation.service.StoreActivityConfigService;
import flex.cc.store.dao.StoreOrderDao;
import flex.cc.store.dto.entity.StoreActivityConfigEntity;
import flex.cc.store.dto.entity.StoreOrderEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Charsets;

import flex.cc.PublicUtil;
import flex.cc.basicinformation.dao.ServiceConfigDao;
import flex.cc.basicinformation.entity.ServiceConfigEntity;
import flex.cc.common.utils.DateUtil;
import flex.cc.common.utils.HttpClientUtil;
import flex.cc.nursing.dao.NursingInterfaceLogDao;
import flex.cc.nursing.dao.NursingOrderDao;
import flex.cc.nursing.dao.NursingSynStatusDao;
import flex.cc.nursing.dto.entity.NursingInterfaceLogEntity;
import flex.cc.nursing.dto.entity.NursingOrderEntity;
import flex.cc.nursing.dto.entity.NursingSynStatusEntity;
import flex.cc.nursing.dto.vo.AppointmentRequestDTO;
import flex.cc.nursing.dto.vo.Request;
import flex.cc.nursing.dto.vo.RequestHead;
import flex.cc.nursing.service.NursingOrderService;
import flex.cc.nursing.util.SignUtil;
import flex.cc.store.dao.StoreCouponDao;
import flex.cc.store.dto.entity.StoreCouponEntity;
import flex.cc.system.dao.DictCodeDao;
import flex.cc.system.entity.DictCodeEntity;
import flex.cc.util.APIConfigUtil;

/**
*
* @author R
* 2022年03月22日  14:04:52
* @desc 护理单实现层
*/
@Service("nursingOrderDriverService")
@Transactional(rollbackFor = Exception.class)
public class NursingOrderServiceImpl implements NursingOrderService {
    private static final Logger logger = LoggerFactory.getLogger(NursingOrderServiceImpl.class);

    @Autowired
    private NursingOrderDao nursingOrderDao;
    @Autowired
    private NursingInterfaceLogDao nursingInterfaceLogDao;
    @Autowired
    private StoreCouponDao storeCouponDao;
    @Autowired
	private APIConfigUtil apiConfigUtil;
    @Resource
	private ServiceConfigDao serviceConfigDao;
    @Resource
	private DictCodeDao dictCodeDao;
    @Autowired
    private NursingSynStatusDao nursingSynStatusDao;
    @Autowired
    private NursingVerifyService nursingVerifyService;
    @Resource
	private StoreOrderDao storeOrderDao;
    @Resource
	private StoreActivityConfigService storeActivityConfigService;

    /**
     * 护理类预约新增
     */
	@Override
	public JSONObject createAppointment(Map<String, Object> requestBodyMap) {
		JSONObject jsonResult = new JSONObject();
		Map<String, Object> dataMap = new HashMap<String, Object>();
		Map<String, Object> serviceMap = new HashMap<String, Object>();
		try {
			NursingOrderEntity nursingOrderEntity = new NursingOrderEntity();
	    		
			//归属卡券码
			String couponNum = (String) requestBodyMap.get("couponNum");
			dataMap.put("orderNo", couponNum);
			nursingOrderEntity.setOrderId(couponNum);
	    	
			//预约时间
			Date appointTime = new Date();
			dataMap.put("appointmentDate", flex.cc.util.DateUtil.DateToString(appointTime, "yyyy-MM-dd HH:mm"));
			nursingOrderEntity.setAppointTime(appointTime);
			
			//联系人姓名
			String contactsName = (String) requestBodyMap.get("contactsName");
			dataMap.put("contactName", contactsName);
			nursingOrderEntity.setContactsName(contactsName);
	    	
			//联系人电话
			String contactsTel = (String) requestBodyMap.get("contactsTel");
			dataMap.put("contactMobile", contactsTel);
			nursingOrderEntity.setContactsTel(contactsTel);
	    	
			//联系人证件类型
			String contactIdType = (String) requestBodyMap.get("contactIdType");
			dataMap.put("contactIdType", contactIdType);
			nursingOrderEntity.setContactIdType(contactIdType);
	    	
			//联系人证件号
			String contactIdNo = (String) requestBodyMap.get("contactIdNo");
			dataMap.put("contactIdNo", contactIdNo);
			nursingOrderEntity.setContactIdNo(contactIdNo);
	    	
			//服务对象与联系人关系
			String relation = (String) requestBodyMap.get("relation");
			dataMap.put("relation", relation);
			nursingOrderEntity.setRelation(relation);
			
			if(relation.equals("1")){
				//1-本人
				//服务对象姓名
				dataMap.put("consumerName", contactsName);
				//服务对象电话
				dataMap.put("consumerMobile", contactsTel);
				//服务对象证件类型
				dataMap.put("consumerIdType", contactIdType);
				//服务对象证件号
				dataMap.put("consumerIdNo", contactIdNo);
			}else{
				//服务对象姓名
				String consumerName = (String) requestBodyMap.get("consumerName");
				dataMap.put("consumerName", consumerName);
				nursingOrderEntity.setConsumerName(consumerName);
				
				//服务对象电话
				String consumerTel = (String) requestBodyMap.get("consumerTel");
				dataMap.put("consumerMobile", consumerTel);
				nursingOrderEntity.setConsumerTel(consumerTel);
				
				//服务对象证件类型
				String consumerIdType = (String) requestBodyMap.get("consumerIdType");
				dataMap.put("consumerIdType", consumerIdType);
				nursingOrderEntity.setConsumerIdType(consumerIdType);
				
				//服务对象证件号
				String consumerIdNo = (String) requestBodyMap.get("consumerIdNo");
				dataMap.put("consumerIdNo", consumerIdNo);
				nursingOrderEntity.setConsumerIdNo(consumerIdNo);
			}
			
			List<Map<String, Object>> serviceList = new ArrayList<Map<String, Object>>();
			//服务分类 默认3-院后上门居家康护服务
			serviceMap.put("serviceCode", "3");
			nursingOrderEntity.setServiceCode("3");
			
			//服务开始时间
			String startDate = (String) requestBodyMap.get("startDate");
			serviceMap.put("startDate", startDate);
			nursingOrderEntity.setStartDate(DateUtil.parseStringToDate(startDate, "yyyy-MM-dd HH:mm:ss"));
			
			//服务对象所在省
			String provinceCode = (String) requestBodyMap.get("provinceCode");
			serviceMap.put("province", provinceCode+"000000");
			nursingOrderEntity.setProvinceCode(provinceCode);
			String province = (String) requestBodyMap.get("province");
			nursingOrderEntity.setProvince(province);
			
			//服务对象所在市
			String cityCode = (String) requestBodyMap.get("cityCode");
			serviceMap.put("city", cityCode+"000000");
			nursingOrderEntity.setCityCode(cityCode);
			String city = (String) requestBodyMap.get("city");
			nursingOrderEntity.setCity(city);

			//服务对象所在区
			String countyCode = (String) requestBodyMap.get("countyCode");
			serviceMap.put("county", countyCode+"000000");
			nursingOrderEntity.setCountyCode(countyCode);
			String county = (String) requestBodyMap.get("county");
			nursingOrderEntity.setCounty(county);
			
			//服务对象所在详细地址
			String address = (String) requestBodyMap.get("address");
			serviceMap.put("address", address);
			nursingOrderEntity.setAddress(address);
			
			serviceList.add(serviceMap);
			dataMap.put("serviceList", serviceList);
			
			logger.info(new Date() + "==" + dataMap.toString());
			
			JSONObject requestJsonObj=new JSONObject(dataMap);

			Date requestDate = new Date();
	        // 调用预约代驾单下单接口
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("couponNum", couponNum);
			StoreCouponEntity couponEntity = storeCouponDao.getOneByParams(params);
			String provider = couponEntity.getServer();
			String createAppointmentUrl = apiConfigUtil.getApiConfig(provider, "nursing_appointment");
			
			String requestJsonStr = requestJsonObj.toString();
			logger.info("护理类预约接口请求报文 ==" + requestJsonStr);
			
			String signKey = apiConfigUtil.getApiConfig(provider, "nursing_signKey");
			String encryptKey = apiConfigUtil.getApiConfig(provider, "nursing_encryptKey");
			String nursingReqId = apiConfigUtil.getApiConfig(provider, "nursing_reqId");
			
			AppointmentRequestDTO appointmentRequestDTO = JSONObject.parseObject(requestJsonStr, AppointmentRequestDTO.class);
			byte[] bytes = SignUtil.aesEncrypt(JSON.toJSONString(appointmentRequestDTO).getBytes(Charsets.UTF_8), SignUtil.decodeHex(encryptKey));
	        String base64 = SignUtil.encodeBase64(bytes);
	        logger.info("【报文加密】{}", base64);

	        Request<String> request = new Request<String>();
	        RequestHead requestHead = new RequestHead();
	        requestHead.setReqId(nursingReqId);
	        requestHead.setVerNo("v001");
	        requestHead.setTransNo(String.format("%025d", Long.parseLong(DateUtil.getCurrentDate("yyyyMMddHHmmssSSS"))));
	        requestHead.setReqTime(DateUtil.getCurrentDate("yyyy-MM-dd HH:mm:ss.SSS"));
	        request.setCommon(requestHead);
	        request.setBody(base64);
	        String content = JSON.toJSONString(request);
			//加密报文
			String sign = SignUtil.generateSign(content, signKey);
			createAppointmentUrl = createAppointmentUrl+"?sign="+sign;
			logger.info("护理类预约接口url ==" + createAppointmentUrl);
			
			requestJsonStr = content.replace("body", "bus_body");
	    	String packageResult = HttpClientUtil.sendHttpPost(createAppointmentUrl, requestJsonStr, new HashMap<String, String>(){{
	            put("Content-Type", "application/json;charset=UTF-8");
	        }});
	    	Date responseDate = new Date();
	    	JSONObject resultObject = JSONObject.parseObject(packageResult);
	    	Map<String, Object> responseBodyMap = resultObject.toJavaObject(Map.class);
	    	
	    	JSONObject commonObject = (JSONObject)responseBodyMap.get("common");
	    	
	    	JSONObject busBodyObject = (JSONObject)responseBodyMap.get("bus_body");
	    	//预约单号
	    	String reserveNo = "";
	    	//请求状态  0成功 1失败
	    	String status = "0";
	    	if(PublicUtil.isNotEmpty(busBodyObject)){
	    		Map<String, Object> busBodyMap = busBodyObject.toJavaObject(Map.class);
		    	reserveNo = (String) busBodyMap.get("reserveNo");
		    	//视频链接
		    	String url = (String) busBodyMap.get("url");
		    	String bussResMsg = (String) busBodyMap.get("bussResMsg");
		    	String bussResCode = (String) busBodyMap.get("bussResCode");
		    	
		    	if(PublicUtil.isNotEmpty(reserveNo)){
		    		//新增预约信息
		    		nursingOrderEntity.setStatus("0".equals(bussResCode)?"00":"01");
		    		nursingOrderEntity.setOrderNo(reserveNo);
			    	nursingOrderEntity.setUpdater("admin");
			    	nursingOrderEntity.setUpdateTime(new Date());
			    	nursingOrderEntity.setCreater("admin");
			    	nursingOrderEntity.setCreateTime(new Date());
			    	nursingOrderEntity.setIsDelete("0".equals(bussResCode)?0:1);
			    	nursingOrderDao.insert(nursingOrderEntity);
			    	
			    	if("0".equals(bussResCode)){
			    		//第一次预约成功请求上游核销
			    		Map<String, Object> paramMap = new HashMap<String, Object>();
			    		paramMap.put("orderId", couponNum);
			    		List<NursingOrderEntity> nursingOrderEntityList = nursingOrderDao.queryNursingOrderList(paramMap);
			    		if(nursingOrderEntityList.size()==1){
			    			nursingVerifyService.verify(reserveNo, couponEntity);
			    		}
			    		
			    		//预约成功默认新增"正在等待安排评估人员,请耐心等待"服务进度
			    		NursingSynStatusEntity nursingSynStatusEntity = new NursingSynStatusEntity();
			    		nursingSynStatusEntity.setReserveNo(reserveNo);
			    		nursingSynStatusEntity.setCouponNum(couponNum);
			    		nursingSynStatusEntity.setServiceStatus("1");
			    		nursingSynStatusEntity.setServiceInfo("正在等待安排评估人员,请耐心等待");
			    		nursingSynStatusEntity.setServiceTime(new Date());
			    		nursingSynStatusEntity.setCreater("admin");
			    		nursingSynStatusEntity.setCreateTime(new Date());
			    		nursingSynStatusEntity.setUpdater("admin");
			    		nursingSynStatusEntity.setUpdateTime(new Date());
			    		nursingSynStatusEntity.setIsDelete(0);
			    		nursingSynStatusDao.insert(nursingSynStatusEntity);
			    		
			    		//更新预约服务单状态为"正在等待安排评估人员,请耐心等待"
			    		Map<String,Object> map = new HashMap<String,Object>();
			    		map.put("status", "1");
			    		map.put("orderNo", reserveNo);
			    		nursingOrderDao.updateByParams(map);
			    	}
		    	}
				jsonResult.put("orderNo", reserveNo); // 预约成功后返回服务单号到前端，用于服务进展页查询当前服务单预约信息
	    		jsonResult.put("resultCode", "0".equals(bussResCode)?"00":"01");
	    		jsonResult.put("resultDesc", "请求预约接口返回结果："+bussResMsg);
	    		
	    		status = "0".equals(bussResCode)?"0":"1";
	    	}else{
	    		if(PublicUtil.isNotEmpty(commonObject)){
		    		Map<String, Object> commonMap = commonObject.toJavaObject(Map.class);
		    		String resMsg = (String) commonMap.get("resMsg");
		    		jsonResult.put("resultCode", "01");
		    		jsonResult.put("resultDesc", "请求预约接口返回结果："+resMsg);
		    		status = "1";
		    	}else{
		    		jsonResult.put("resultCode", "01");
		    		jsonResult.put("resultDesc", "请求预约接口返回结果为空");
		    		status = "1";
		    	}
	    	}
	    	//新增接口日志信息
	    	NursingInterfaceLogEntity nursingInterfaceLogEntity = new NursingInterfaceLogEntity();
	    	nursingInterfaceLogEntity.setOrderNo(reserveNo);
	    	nursingInterfaceLogEntity.setOrderId(couponNum);
	    	nursingInterfaceLogEntity.setStatus(status);
	    	nursingInterfaceLogEntity.setInterfaceName("护理类预约接口");
	    	nursingInterfaceLogEntity.setRequestTime(requestDate);
	    	nursingInterfaceLogEntity.setRequestBody(requestJsonObj.toString());
	    	nursingInterfaceLogEntity.setResponseBody(resultObject.toString());
	    	nursingInterfaceLogEntity.setResponseTime(responseDate);
	    	nursingInterfaceLogEntity.setCreateTime(new Date());
	    	nursingInterfaceLogDao.insert(nursingInterfaceLogEntity);
	    	
	    	return jsonResult;
		} catch (Exception e) {
			logger.info("护理类预约接口异常"+e.getMessage());
			jsonResult.put("resultCode", "01");
    		jsonResult.put("resultDesc", "护理类预约接口异常");
            return jsonResult;
		}
	}

	/**
	 * @param params 查询条件
	 * @return
	 * @description 根据查询参数，获取护理单
	 * @author wkangle
	 * @time 2022/03/23 0023 13:45
	 * @exception/throws
	 */
	@Override
	public NursingOrderEntity queryOneByParams(Map<String, Object> params) {
		List<NursingOrderEntity> nursingOrderEntityList = nursingOrderDao.queryNursingOrderList(params);
		return nursingOrderEntityList.size() > 0 ? nursingOrderEntityList.get(0) : null;
	}

	/**
	 * @param params 卡券信息
	 * @return
	 * @description 根据卡券信息查询对应的护理单列表
	 * @author wkangle
	 * @time 2022/03/23 0023 15:27
	 * @exception/throws
	 */
	@Override
	public List<NursingOrderEntity> queryNursingOrderList(Map<String, Object> params) {
		return nursingOrderDao.queryNursingOrderList(params);
	}

	/**
	 * @param activityId 服务项目编号
	 * @return
	 * @description 根据护理类卡券服务项目编号查询对应的标签信息
	 * @author wkangle
	 * @time 2022/03/24 0024 14:21
	 * @exception/throws
	 */
	@Override
	public List<DictCodeEntity> queryNursingTags(String activityId) {
		Map<String, Object> activityParams = new HashMap<String, Object>();
		activityParams.put("status", '0');
		activityParams.put("serviceCode", activityId);
		ServiceConfigEntity serviceConfigEntity = serviceConfigDao.getOneByParams(activityParams);
		String tags = serviceConfigEntity.getTags();
		String[] split = PublicUtil.isNotEmpty(tags) ? tags.split(",") : null;
		List<DictCodeEntity> list = new ArrayList<>();
		if (split != null) {
			Map<String, Object> dictCodeParams = new HashMap<String, Object>();
			dictCodeParams.put("typeCode", "nursingTags");
			for (String tagCode: split) {
				dictCodeParams.put("code", tagCode);
				DictCodeEntity dictCodeEntity = dictCodeDao.getOneByParams(dictCodeParams);
				list.add(dictCodeEntity);
			}
		}
		return list;
	}

	/**
	 * @param couponNum
	 * @return
	 * @description 根据卡券码，查询对应服务包配置的最大允许使用次数
	 * @author wkangle
	 * @time 2022/04/07 0007 9:39
	 * @exception/throws
	 */
	@Override
	public Number queryMaxTimes(String couponNum) {
		Number maxTimes = 0;
		Map<String, Object> params = new HashMap<>();
		params.put("couponNum", couponNum);
		StoreCouponEntity storeCouponEntity = storeCouponDao.getOneByParams(params);
		if (storeCouponEntity == null) {
			return maxTimes;
		}
		String activityId = storeCouponEntity.getActivityId(); // 服务项目编码
		String orderId = storeCouponEntity.getOrderId(); // 归属订单号

		StoreOrderEntity storeOrderEntity = storeOrderDao.queryByOrderId(orderId);
		if (storeOrderEntity == null) {
			return maxTimes;
		}
		String serviceItemCode = storeOrderEntity.getServiceItemCode();

		Map<String, Object> reqVo = new HashMap<>();
		reqVo.put("configCode", serviceItemCode);
		reqVo.put("activityCode", activityId);
		List<StoreActivityConfigEntity> storeActivityConfigEntities = storeActivityConfigService.queryActivityConfig(reqVo);
		maxTimes = storeActivityConfigEntities.size() > 0 ? Integer.valueOf(storeActivityConfigEntities.get(0).getUsageCount()) : 0;
		return maxTimes;
	}
}
